﻿using System;
using System.Collections.Generic;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.ServiceModel;
using System.Text;
using System.Drawing;
using System.Xml;
using System.Xml.Linq;
using ReporterEngine;
using System.Threading.Tasks;
using System.IO.Packaging;
//using ReporterSystem.SharepointServiceReference;
using System.Data.Services.Client;
//using Microsoft.SharePoint.Client;

//using SharepointConnector;

namespace ReporterSystem
{
    public static class ReportApp
    {
        //load project

        //create report project
        //delete report project

        //add template
        //report

        //import cif

        //error, warning status

        public static string MyDocumentsFolder =Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),"Provision Reports");


        //event for message window
        public static event BoolMessageHandler OnUpdateTemplate;
        public static event BoolMessageHandler OnUpdateImages;
        public static event BoolMessageHandler OnUpdateCif;

        private const string ReportProjectIDField = "Report Project ID";
        private const string PublishDatetimeField = "Published_x0200_Datetime";

        public static void PublishProject(ReportProject project, PublishStatus status)
        {
           // var imagePath = GetExportPath(project);
           // imagePath = Path.Combine(imagePath, "images");

           // var imageFiles = Directory.GetFiles(imagePath, "*.*");


           // status.TotalImages = imageFiles.Length;
           // status.TotalNotebooks = project.Templates.Count;
           // status.Change();


           // var projectInfo = new FileInfo(project.ActualFilePath);
           //// var svcProjet = new svcpvProject {Name = project.Name, ProjectID = project.ProjectID.ToString(),PublishedDateTime = projectInfo.LastWriteTimeUtc};




           // using (ClientContext ctx = new ClientContext("http://pvreporter.novitech.sk/"))
            //{
                
            //    ctx.AuthenticationMode = ClientAuthenticationMode.FormsAuthentication; // Default / Anonymous

            //    ctx.AuthenticationMode = ClientAuthenticationMode.FormsAuthentication;
            //    FormsAuthenticationLoginInfo fbaInfo = new FormsAuthenticationLoginInfo("vavrikdavid", "huhuhaha");

            //    ctx.FormsAuthenticationLoginInfo = fbaInfo;

            //    Web site = ctx.Web;

            //    //ctx.Load(site);
            //    //ctx.Load(site.Lists);
                

            //    var list = site.Lists.GetByTitle("ReportLibrary");

            //    ctx.Load(list);
            //    ctx.Load(list.RootFolder);
            //    ctx.Load(site.Fields);
            //    ctx.Load(site.ContentTypes);
            //   ctx.ExecuteQuery();

            //   var fields = site.Fields.ToList().Where(x=>x.TypeDisplayName.Contains("Report")).ToList();
            //    var types = site.ContentTypes.ToList().Where(x => x.Name.Contains("ReporterService - pvProject")).ToList().First();
               
            //    //list.Fields.

            //    //site.Fields.Add(new Field(ctx,ObjectPath))

            //    ctx.Load(types.Fields);
            //    ctx.ExecuteQuery();

            //    var tfileds = types.Fields.ToList();

            //    string url = list.DefaultViewUrl;

            //    ListItemCreationInformation newFolder = new ListItemCreationInformation{UnderlyingObjectType = FileSystemObjectType.Folder};
            //    newFolder.FolderUrl = list.RootFolder.ServerRelativeUrl;// + "/" + project.Name;
            //    newFolder.LeafName = project.Name;
            //    newFolder.UnderlyingObjectType = FileSystemObjectType.Folder;

                
            //    var newFolderItem = list.AddItem(newFolder);


            //    newFolderItem.Update();
            //    ctx.ExecuteQuery();
            //    //newFolderItem["Title"] = project.Name;
            //    //newFolderItem[PublishDatetimeField] = projectInfo.LastWriteTimeUtc;
            //    newFolderItem["ContentType"] = "ReporterService - pvProject";

            //    newFolderItem.Update();

            //    ctx.Load(newFolderItem);
            //    ctx.ExecuteQuery();

            //    newFolderItem.RefreshLoad();
            //    ctx.ExecuteQuery();
            //   // ctx.ExecuteQuery();
            //  //  newFolderItem.Update();
            //   // newFolderItem[ReportProjectIDField] = project.ProjectID;
            //    newFolderItem["Report Project ID"] = project.ProjectID.ToString();
            //    newFolderItem.Update();

                
                
            //    ctx.ExecuteQuery();


            //    status.ProjectPublished = true;
            //    status.Change();

            //    foreach (var template in project.Templates)
            //    {
            //       // var newTemplate = new svcpvTemplate();
            //      //  newTemplate.Name = template.TemplateFileName;
            //      //  newTemplate.TemplateID = template.ReportTemplateID.ToString();
            //        //newTemplate.

            //        string templateFile = GetTemplatePath(project, template);
            //        if (System.IO.File.Exists(templateFile))
            //        {
            //            var templateInfo = new FileInfo(templateFile);
            //          //  newTemplate.PublishedDateTime = templateInfo.LastWriteTimeUtc;

            //         //   newTemplate.Content = System.IO.File.ReadAllBytes(templateFile);

            //            // var result = clinet.UpdateTemplate(newTemplate, svcProjet.ProjectID);

            //            //if(result.UseServerVersion)
            //            //{
            //            //    //confirm window
            //            //    if (OnUpdateTemplate != null)
            //            //    {
            //            //        var updateResult = OnUpdateTemplate(template.TemplateFileName);

            //            //        if(updateResult)
            //            //        {
            //            //            File.WriteAllBytes(templateFile,result.Content);
            //            //            templateInfo.LastWriteTimeUtc = result.PublishedDateTime;
            //            //        }
            //            //    }
            //            //}
            //        }

            //        status.PublishedNotebooks++;
            //        status.Change();
            //    }

            //    //update cif
            //    var cifFile = GetCifPath(project);

            //    if (System.IO.File.Exists(cifFile))
            //    {
            //       // var newcif = new svcpvCif();

            //        var cifInfo = new FileInfo(cifFile);
            //      //  newcif.PublishedDateTime = cifInfo.LastWriteTimeUtc;

            //     //   newcif.Content = System.IO.File.ReadAllBytes(cifFile);

            //        //var result = clinet.UpdateCif(newcif, svcProjet.ProjectID);
            //    }

            //    status.CifPublished = true;
            //    status.Change();


            //    foreach (var file in imageFiles)
            //    {
            //        var fileInfo = new FileInfo(file);

            //       // var newImage = new svcpvImage();
            //      //  newImage.FullFileName = fileInfo.Name;

            //      //  newImage.PublishedDateTime = fileInfo.LastWriteTimeUtc;

            //      //  newImage.Content = System.IO.File.ReadAllBytes(file);

            //        // var result = clinet.UpdateImage(newImage, svcProjet.ProjectID);

            //        status.PublishedImages++;
            //        status.Change();
            //    }

            //    status.Done = true;
            //    status.Change();
            //}
        }

        public static List<ReportProject> LoadMyProjects()
        {
            //TestService();

          

            ValidateProjectFolder();

            List<ReportProject> result = new List<ReportProject>();

            var projectFiles = Directory.GetFiles(MyDocumentsFolder, "*.preportinfo", SearchOption.AllDirectories);

            foreach (var projFile in projectFiles.OrderBy(x=>x))
            {
                string file = projFile;


                var projFileContent = System.IO.File.ReadAllText(file);

                ReportProject rp = ReportProject.Load(projFileContent);
                rp.ActualFilePath = file;

                result.Add(rp);

                //PublishProject(rp);
            }

            


            return result;
        }

        public static string GetTemplatePath(ReportProject project,ReportTemplate template)
        {
            var projectFolder = Path.Combine(MyDocumentsFolder, project.Name);

            var templatesFolder = Path.Combine(projectFolder, "Templates");

            var resultFile = Path.Combine(templatesFolder, template.TemplateFileName + ".docx");
            return resultFile;
        }

        public static string GetResultPath(ReportProject project, ReportTemplate template)
        {
            var projectFolder = Path.Combine(MyDocumentsFolder, project.Name);

            var templatesFolder = Path.Combine(projectFolder, "Results");

            var resultFile = Path.Combine(templatesFolder, template.ResultFileName + ".docx");
            return resultFile;
        }

        public static string GetExportPath(ReportProject project)
        {
            var projectFolder = Path.Combine(MyDocumentsFolder, project.Name);

            var resultFolder = Path.Combine(projectFolder, "Export");

            return resultFolder;
        }

        public static string GetCifPath(ReportProject project)
        {
            var projectFolder = Path.Combine(MyDocumentsFolder, project.Name);

            var templatesFolder = Path.Combine(projectFolder, "Export");

            var resultFile = Path.Combine(templatesFolder, "cif.xml");
            return resultFile;
        }

        public static CIFModel GetModel(ReportProject project)
        {
            if (project.ActualModel == null)
            {
                using (var stream = ReportManager.Provider.GetCif(project.Name))
                {
                    var cif = XDocument.Load(stream);

                    var cifModel = new CIFModel();

                    cifModel.Parse(cif);

                    project.ActualModel = cifModel;
                }
            }

            return project.ActualModel;
        }

        public static CIFModel GetNewModel(ReportProject project)
        {
            using (var stream = ReportManager.Provider.GetCif(project.Name))
            {
                var cif = XDocument.Load(stream);

                var cifModel = new CIFModel();

                cifModel.Parse(cif);

                return cifModel;
            }
        }

        public static XDocument GetTemplateDocumetContent(ReportTemplate template, ReportProject project)
        {
            //var templatePath = GetTemplatePath(project, template);
            XDocument result = new XDocument();

            using (var stream = ReportManager.Provider.GetTemplate(project.Name,template.TemplateFileName))
            {
                using (var package = Package.Open(stream))
                {
                    var replaceList = package.GetParts().ToList();

                    foreach (var part in replaceList)
                    {
                        var partPath = part.Uri.ToString();

                        if (partPath.EndsWith("document.xml"))
                        {
                            using (var stream1 = part.GetStream())
                            {
                                if (partPath.EndsWith(".xml"))
                                {
                                    XmlReader sr = XmlReader.Create(stream1);
                                    XDocument xtpl = XDocument.Load(sr);

                                    result = xtpl;
                                }
                            }
                        }
                    }
                }
            }


            return result;
        }

        public static void CreateReportProject(ReportProject project)
        {
            ValidateProjectFolder();

            if (project.ProjectID == Guid.Empty)
                project.ProjectID = Guid.NewGuid();

            //validate project name
            var projectFolder = Path.Combine(MyDocumentsFolder, project.Name);
            Directory.CreateDirectory(projectFolder);

            project.ActualFilePath = Path.Combine(projectFolder, "reportinfo.preportinfo");

            var exportFolder = Path.Combine(projectFolder, "Export");
            Directory.CreateDirectory(exportFolder);

            var exportImagesFolder = Path.Combine(exportFolder, "Images");
            Directory.CreateDirectory(exportImagesFolder);

            var resultsFolder = Path.Combine(projectFolder, "Results");
            Directory.CreateDirectory(resultsFolder);

            var templatesFolder = Path.Combine(projectFolder, "Templates");
            Directory.CreateDirectory(templatesFolder);


            UpdateProjectInfo(project);
        }

        public static void DeleteReportProject(ReportProject project)
        {
            ValidateProjectFolder();

            //validate project name
            Directory.Delete(Path.Combine(MyDocumentsFolder, project.Name),true);

        }

        public static void CreateTemplate(ReportTemplate template, ReportProject project)
        {
            //create template
            if (template.ReportTemplateID == Guid.Empty)
                template.ReportTemplateID = Guid.NewGuid();

            project.Templates.Add(template);

            UpdateProjectInfo(project);
            //update project info file
        }

        public static void UpdateTemplate(ReportTemplate template, ReportProject project, string templateName, string resultName)
        {
            if(string.IsNullOrEmpty(template.TemplateFileName) && !string.IsNullOrEmpty(templateName))
            {
                string projFolder = Path.Combine(MyDocumentsFolder, project.Name);
                string templatesFolder = Path.Combine(projFolder,"templates");
                string templateFile = Path.Combine(templatesFolder, templateName + ".docx");

                System.IO.File.Create(templateFile).Close();
            }

            if (!string.IsNullOrEmpty(template.TemplateFileName) &&template.TemplateFileName != templateName)
            {
                string projFolder = Path.Combine(MyDocumentsFolder, project.Name);
                string templatesFolder = Path.Combine(projFolder, "templates");
                string templateNewFile = Path.Combine(templatesFolder, templateName + ".docx");
                string templateOldFile = Path.Combine(templatesFolder, template.TemplateFileName + ".docx");

                System.IO.File.Move(templateOldFile, templateNewFile);
            }
        }

        public static void DeleteTemplate(ReportTemplate template, ReportProject project)
        {
            project.Templates.RemoveAll(x=>x.ReportTemplateID == template.ReportTemplateID);

            UpdateProjectInfo(project);
            
            //TODO: delete all associated files
            string projFolder = Path.Combine(MyDocumentsFolder, project.Name);
            string templatesFolder = Path.Combine(projFolder, "templates");
            string templateFile = Path.Combine(templatesFolder, template.TemplateFileName + ".docx");

            string resultsFolder = Path.Combine(projFolder, "results");
            string resultFile = Path.Combine(resultsFolder, template.ResultFileName + ".docx");

            if (System.IO.File.Exists(templateFile))
                System.IO.File.Delete(templateFile);

            if (System.IO.File.Exists(resultFile))
                System.IO.File.Delete(resultFile);
        }

        public static void UpdateProjectInfo(ReportProject project)
        {
            //var projectFolder = Path.Combine(MyDocumentsFolder, project.Name);
            var projectFile = project.ActualFilePath;

            //var projectFile = Path.Combine(projectFolder, "reportinfo.preportinfo");
            System.IO.File.WriteAllText(projectFile, ReportProject.Save(project));
        }



        public static void ValidateProjectFolder()
        {
            if (!Directory.Exists(MyDocumentsFolder))
            {
                Directory.CreateDirectory(MyDocumentsFolder);
            }
        }

        public static bool CheckIfExistsReportProjectName(string projectName)
        {
            return Directory.Exists(Path.Combine(MyDocumentsFolder, projectName));
        }

        public static bool ImportProvision(ReportProject project, bool importImages)
        {
            try
            {
                cifRequest cRequest = new cifRequest();

                var projectfolder = Path.Combine(MyDocumentsFolder, project.Name);
                var exportFolder = Path.Combine(projectfolder, "export");
                var exportFile = Path.Combine(exportFolder, "cif.xml");
                var strRequestFile = Path.Combine(exportFolder, "cifReportRequest.xml");
                var imagesFolder = Path.Combine(exportFolder, "images");


                string strXmlPath = exportFile;
                string path = imagesFolder;


                cRequest.ResultFile = strXmlPath;
                cRequest.ExportingAllFields = true;
                cRequest.RawNumbers = true;
                cRequest.LocalInvariant = true;
                cRequest.QualifiedNames = true;
                cRequest.GeneratingExtensions = false;
                if (importImages)//check if export images
                {
                    cRequest.Images = true;//TODO: set by variable
                    cRequest.ImageTarget = path;
                    cRequest.ImageFormat = "BMP";//EMF,JPG
                }

                var importResult = new cifRequestHandler().AcceptRequest(cRequest, strRequestFile);

                if (!importResult)
                    return false;

                //convert all bmp to jpeg

                var files = Directory.GetFiles(imagesFolder, "*.bmp");
                foreach (var file in files)
                {
                    using (Image img = Image.FromFile(file))
                    {
                        img.Save(file.Replace(".bmp", ".jpg"), ImageFormat.Jpeg);
                    }

                    System.IO.File.Delete(file);
                }


                XDocument xNotebook = XDocument.Load(exportFile);
                //set actual notebook info into project
                project.Notebook.NotebookName = xNotebook.Root.Element("notebook").Attribute("name").Value;
                project.Notebook.LastImportDate = DateTime.Now;
                project.Notebook.ProvisionVersion = xNotebook.Root.Attribute("toolVersion").Value;
                project.Notebook.Updated = DateTime.Parse(xNotebook.Root.Descendants().Where(x => x.Name.LocalName == "createTime").First().Value);

                UpdateProjectInfo(project);
            }
            catch (COMException)
           {
               return false;
           }

            return true;
        }
    }
}
